package com.ruoyi.web.service.Impl;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.stream.Collectors;

import com.ruoyi.common.config.RuoYiConfig;
import com.ruoyi.common.core.domain.AjaxResult;
import com.ruoyi.common.exception.base.BaseException;
import com.ruoyi.common.utils.DateUtils;
import com.ruoyi.common.utils.SecurityUtils;
import com.ruoyi.common.utils.pinyin.PinYinUtils;
import com.ruoyi.web.domain.mes.*;
import com.ruoyi.web.domain.vo.WasteVo;
import com.ruoyi.web.mapper.MesConfigMapper;
import com.ruoyi.web.mapper.MesCustomMapper;
import com.ruoyi.web.mapper.MesWasteMapper;
import com.ruoyi.web.service.IMesWasteService;
import org.apache.poi.ss.usermodel.*;
import org.apache.poi.ss.util.CellRangeAddress;
import org.apache.poi.xssf.streaming.SXSSFRow;
import org.apache.poi.xssf.streaming.SXSSFSheet;
import org.apache.poi.xssf.streaming.SXSSFWorkbook;
import org.springframework.stereotype.Service;

import com.ruoyi.common.utils.StringUtils;
import org.springframework.transaction.annotation.Transactional;
import com.ruoyi.web.mapper.MesWastesettleMapper;
import com.ruoyi.web.service.IMesWastesettleService;

import javax.annotation.Resource;

/**
 * 废料结算Service业务层处理
 *
 * @author levicash
 * @date 2024-01-24
 */
@Service
public class MesWastesettleServiceImpl implements IMesWastesettleService {
    @Resource
    private MesWastesettleMapper mesWastesettleMapper;

    @Resource
    private IMesWasteService mesWasteService;

    @Resource
    private MesConfigMapper configMapper;

    @Resource
    private MesCustomMapper mesCustomMapper;

    /**
     * 查询废料结算
     *
     * @param id 废料结算主键
     * @return 废料结算
     */
    @Override
    public MesWastesettle selectMesWastesettleById(Long id) {
        return mesWastesettleMapper.selectMesWastesettleById(id);
    }

    /**
     * 查询废料结算列表
     *
     * @param mesWastesettle 废料结算
     * @return 废料结算
     */
    @Override
    public List<MesWastesettle> selectMesWastesettleList(MesWastesettle mesWastesettle) {
        return mesWastesettleMapper.selectMesWastesettleList(mesWastesettle);
    }

    /**
     * 新增废料结算
     *
     * @param mesWastesettle 废料结算
     * @return 结果
     */
    @Transactional
    @Override
    public int insertMesWastesettle(MesWastesettle mesWastesettle) {
        mesWastesettle.setCreateBy(SecurityUtils.getUsername());
        // 获取前端新增时间
        mesWastesettle.setCreateTime(mesWastesettle.getCreateTime());

        // 生成废料结算单编号
        Map<String, Object> map = new HashMap<>();
        map.put("columnName", "code");
        map.put("tableName", "mes_wastesettle");
        int maxNum = configMapper.getMaxId(map);
        String code = PinYinUtils.getCodeNormal(maxNum, "FLJSD");
        mesWastesettle.setCode(code);
        // 添加废料结算
        int rows = mesWastesettleMapper.insertMesWastesettle(mesWastesettle);
        // 添加废料结算详情
        for (MesWastesettleDetail itemDetail : mesWastesettle.getMesWastesettleDetailList()) {
            itemDetail.setWastesettleCode(code);
        }
        insertMesWastesettleDetail(mesWastesettle);

        int bakId = mesWastesettle.getId().intValue();
        return bakId;
    }

    /**
     * 修改废料结算
     *
     * @param mesWastesettle 废料结算
     * @return 结果
     */
    @Transactional
    @Override
    public int updateMesWastesettle(MesWastesettle mesWastesettle) {
        mesWastesettle.setUpdateBy(SecurityUtils.getUsername());
        mesWastesettle.setUpdateTime(DateUtils.getNowDate());
        int status = mesWastesettle.getStatus();
        if (status == 1) {// 提交
            //20240322 作废
//            MesWastesettle Info = mesWastesettleMapper.selectMesWastesettleById(mesWastesettle.getId()); // 查询数据库
//            List<MesWastesettleDetail> DetailList = Info.getMesWastesettleDetailList();
            // 回写废料处理已收金额
//            for (MesWastesettleDetail Detail : DetailList) {
//                MesWaste wasteCurrent = mesWasteMapper.selectMesWasteByCode(Detail.getWasteCode());
//                BigDecimal amount = (Detail.getAmount() != null) ? Detail.getAmount() : BigDecimal.ZERO; // 实收金额
//                BigDecimal amountReceived = (wasteCurrent.getAmountReceived() != null) ? wasteCurrent.getAmountReceived() : BigDecimal.ZERO; // 当前废料处理已收金额
//                BigDecimal amountSum = (wasteCurrent.getAmountSum() != null) ? wasteCurrent.getAmountSum() : BigDecimal.ZERO;     // 当前废料处理总金额
//
//                int result = (amountReceived.add(amount)).compareTo(amountSum);
//                if (result > 0) {
//                    throw new ServiceException("实收金额加已收金额大于总金额！");
//                } else {
//                    BigDecimal sumAmount = amountReceived.add(amount);
//                    wasteCurrent.setAmountReceived(sumAmount);
//                }
//                mesWasteMapper.updateMesWaste(wasteCurrent);
//            }

            //回写客户基本信息上的结余:总结余-本次结算金额totalAmountUnsettled
            MesCustom mesCustom=new MesCustom();
            BigDecimal totalAmountUnsettled=mesWastesettle.getTotalAmountUnsettled()!=null ?mesWastesettle.getTotalAmountUnsettled():BigDecimal.ZERO;//总结余（欠款）
            BigDecimal amount=mesWastesettle.getAmount()!=null ?mesWastesettle.getAmount():BigDecimal.ZERO;//结算金额
            BigDecimal amountArrears = totalAmountUnsettled.subtract(amount); //本地结余
            mesCustom.setId(mesWastesettle.getCollectionDeptId());
            mesCustom.setTotalAmountArrears(amountArrears);
            mesWastesettle.setTotalAmountArrears(amountArrears);
            mesCustomMapper.updateMesCustom(mesCustom);

        } else {
            mesWastesettleMapper.deleteMesWastesettleDetailByWastesettleCode(mesWastesettle.getCode());
            insertMesWastesettleDetail(mesWastesettle);
        }

        return mesWastesettleMapper.updateMesWastesettle(mesWastesettle);
    }

    /**
     * 批量删除废料结算
     *
     * @param ids 需要删除的废料结算主键
     * @return 结果
     */
    @Transactional
    @Override
    public int deleteMesWastesettleByIds(Long[] ids) {
        List<String> codes = new ArrayList<>();
        List<MesWastesettle> list = mesWastesettleMapper.selectMesWastesettleByIds(ids);
        if (list.size() > 0) {
            for (MesWastesettle item : list) {
                codes.add(item.getCode());
            }
            String array[] = codes.toArray(new String[0]);
            mesWastesettleMapper.deleteMesWastesettleDetailByWastesettleCodes(array);

        }
        return mesWastesettleMapper.deleteMesWastesettleByIds(ids);
    }

    /**
     * 删除废料结算信息
     *
     * @param id 废料结算主键
     * @return 结果
     */
    @Transactional
    @Override
    public int deleteMesWastesettleById(Long id) {
        MesWastesettle wastesettle = mesWastesettleMapper.selectMesWastesettleById(id);
        mesWastesettleMapper.deleteMesWastesettleDetailByWastesettleCode(wastesettle.getCode());
        return mesWastesettleMapper.deleteMesWastesettleById(id);
    }

    /**
     * 新增废料结算明细信息
     *
     * @param mesWastesettle 废料结算对象
     */
    public void insertMesWastesettleDetail(MesWastesettle mesWastesettle) {
        List<MesWastesettleDetail> mesWastesettleDetailList = mesWastesettle.getMesWastesettleDetailList();
        String wasteSettleCode = mesWastesettle.getCode();
        if (StringUtils.isNotNull(mesWastesettleDetailList)) {
            List<MesWastesettleDetail> list = new ArrayList<MesWastesettleDetail>();
            for (MesWastesettleDetail mesWastesettleDetail : mesWastesettleDetailList) {
                mesWastesettleDetail.setCreateBy(SecurityUtils.getUsername());
                mesWastesettleDetail.setCreateTime(mesWastesettle.getCreateTime());
                mesWastesettleDetail.setWastesettleCode(wasteSettleCode);
//                BigDecimal wasteSum = mesWastesettleDetail.getWasteSum(); // 废料单据金额
//                BigDecimal wasteReceived = mesWastesettleDetail.getWasteReceived(); // 废料已收金额
//                BigDecimal wasteNoReceived = wasteReceived.subtract(wasteSum); // 计算未收金额
//                mesWastesettleDetail.setWasteNoreceived(wasteNoReceived);
                list.add(mesWastesettleDetail);
            }
            if (list.size() > 0) {
                mesWastesettleMapper.batchMesWastesettleDetail(list);
            }
        }
    }

    /**
     * 导出结算信息
     * @Date: 2024年6月21日
     * @Auth: 张恒
     */
    public AjaxResult exportSettle(MesWastesettle setting){
        //创建Workbook对象(excel的文档对象)
        SXSSFWorkbook swb = new SXSSFWorkbook(100);
        //标题样式
        CellStyle titleStyle = swb.createCellStyle();
        titleStyle.setAlignment(HorizontalAlignment.CENTER);// 水平居中
        titleStyle.setVerticalAlignment(VerticalAlignment.CENTER);//垂直居中
        titleStyle.setFillForegroundColor((short) 22);
        titleStyle.setFillPattern(FillPatternType.SOLID_FOREGROUND);
        titleStyle.setBorderBottom(BorderStyle.THIN); //下边框
        titleStyle.setBorderLeft(BorderStyle.THIN);//左边框
        titleStyle.setBorderTop(BorderStyle.THIN);//上边框
        titleStyle.setBorderRight(BorderStyle.THIN);//右边框
        // 设置字体
        Font font = swb.createFont();
        font.setBold(true);
        titleStyle.setFont(font);

        //单元格样式
        CellStyle cellStyle = swb.createCellStyle();
        cellStyle.setAlignment(HorizontalAlignment.CENTER);//水平居中
        cellStyle.setVerticalAlignment(VerticalAlignment.CENTER);
        cellStyle.setBorderBottom(BorderStyle.THIN); //下边框
        cellStyle.setBorderLeft(BorderStyle.THIN);//左边框
        cellStyle.setBorderTop(BorderStyle.THIN);//上边框
        cellStyle.setBorderRight(BorderStyle.THIN);//右边框
        // 设置字体
        Font cellFont = swb.createFont();
        cellStyle.setFont(cellFont);

        //建立新的sheet页
        SXSSFSheet sheet = swb.createSheet("结算信息");

        // 创建主标题行
        // 合并
        sheet.addMergedRegion(new CellRangeAddress(0, 0, 0, 5));
        // 创建合并行数据
        SXSSFRow rowOne = sheet.createRow(0);
        rowOne.createCell(0).setCellValue(setting.getYears() + "年结算信息");
        rowOne.setHeight((short) 800);
        CellStyle titleStyleOne = swb.createCellStyle();
        titleStyleOne.setAlignment(HorizontalAlignment.CENTER);// 水平居中
        titleStyleOne.setVerticalAlignment(VerticalAlignment.CENTER);//垂直居中
        titleStyleOne.setBorderBottom(BorderStyle.THIN); //下边框
        titleStyleOne.setBorderLeft(BorderStyle.THIN);//左边框
        titleStyleOne.setBorderTop(BorderStyle.THIN);//上边框
        titleStyleOne.setBorderRight(BorderStyle.THIN);//右边框
        // 设置字体
        Font fontOne = swb.createFont();
        fontOne.setBold(true);
        fontOne.setFontHeightInPoints((short) 20);
        titleStyleOne.setFont(fontOne);
        for (int i = 0; i <= 5; i++) {
            // 创建缺失行
            if(i != 0) rowOne.createCell(i);
            //设置单元格样式
            rowOne.getCell(i).setCellStyle(titleStyleOne);
        }

        // 内容标题
        CellStyle titleStyleTwo = swb.createCellStyle();
        titleStyleTwo.setAlignment(HorizontalAlignment.CENTER);// 水平居中
        titleStyleTwo.setVerticalAlignment(VerticalAlignment.CENTER);//垂直居中
        titleStyleTwo.setBorderBottom(BorderStyle.THIN); //下边框
        titleStyleTwo.setBorderLeft(BorderStyle.THIN);//左边框
        titleStyleTwo.setBorderTop(BorderStyle.THIN);//上边框
        titleStyleTwo.setBorderRight(BorderStyle.THIN);//右边框
        // 设置字体
        Font fontTwo = swb.createFont();
        fontTwo.setBold(true);
        fontTwo.setFontHeightInPoints((short) 11);
        titleStyleTwo.setFont(fontTwo);

        // 获取年份
        Integer year = setting.getYears();
        // 查询上年结余金额 = 废料处理合计 - 废料结算单
        BigDecimal decimal = mesWastesettleMapper.selectMesWasteSum(year - 1);
        // 创建上年结余金额：合并
        sheet.addMergedRegion(new CellRangeAddress(1, 1, 0, 3));
        sheet.addMergedRegion(new CellRangeAddress(1, 1, 4, 5));
        // 创建合并行数据
        SXSSFRow rowTwo = sheet.createRow(1);
        rowTwo.createCell(0).setCellValue("上年结余金额");
        rowTwo.createCell(4).setCellValue(decimal.setScale(2, RoundingMode.HALF_UP).stripTrailingZeros().toPlainString());
        rowTwo.setHeight((short) 400);
        for (int i = 0; i <= 5; i++) {
            // 创建缺失行
            if(i != 0 && i != 4) rowTwo.createCell(i);
            //设置单元格样式
            if(i < 4) rowTwo.getCell(i).setCellStyle(titleStyle);
            else rowTwo.getCell(i).setCellStyle(titleStyleTwo);
        }

        //【4】创建标题行
        SXSSFRow row = sheet.createRow(2);
        row.createCell(0).setCellValue("序号");
        row.createCell(1).setCellValue("汇款日期");
        row.createCell(2).setCellValue("汇款形式");
        row.createCell(3).setCellValue("银行");
        row.createCell(4).setCellValue("持卡人");
        row.createCell(5).setCellValue("金额");
        for (int i = 0; i <= 5; i++) {
            //设置表格列宽度为5000个字节
            sheet.setColumnWidth(i, 5000);
            //设置单元格样式
            row.getCell(i).setCellStyle(titleStyle);
        }
        // 查询本年收款明细
        MesWastesettle mesWastesettle = new MesWastesettle();
        mesWastesettle.setYears(year);
        List<MesWastesettle> mesWastesettles = mesWastesettleMapper.selectMesWastesettleList(mesWastesettle);

        int i = 3;
        BigDecimal amountSum = new BigDecimal(0);
        // 判断是否有数据
        if(mesWastesettles.size() > 0){
            SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd");
            for (MesWastesettle wastesettle : mesWastesettles) {
                row = sheet.createRow(i);
                String collectionDate = "";
                if(wastesettle.getCollectionDate() != null){
                    collectionDate = dateFormat.format(wastesettle.getCollectionDate());
                }
                String collectionType = StringUtils.isNotEmpty(wastesettle.getCollectionType()) ?
                        ("1".equals(wastesettle.getCollectionType()) ? "现金" : "转账") : "";
                row.createCell(0).setCellValue(i - 2);
                row.createCell(1).setCellValue(collectionDate);
                row.createCell(2).setCellValue(collectionType);
                row.createCell(3).setCellValue(wastesettle.getBankcardNumber());
                row.createCell(4).setCellValue(wastesettle.getCardholder());
                row.createCell(5).setCellValue(wastesettle.getAmount() == null ? "0" : wastesettle.getAmount().toPlainString());
                // 设置样式
                for (int j = 0; j <= 5; j++) {
                    row.getCell(j).setCellStyle(cellStyle);
                }
                amountSum = amountSum.add(wastesettle.getAmount() == null ? new BigDecimal("0") : wastesettle.getAmount());
                i++;
            }
        }

        // 创建总汇入金额
        sheet.addMergedRegion(new CellRangeAddress(i + 1, i + 1, 0, 3));
        sheet.addMergedRegion(new CellRangeAddress(i + 1, i + 1, 4, 5));
        // 创建合并行数据
        SXSSFRow rowLastOne = sheet.createRow(i + 1);
        rowLastOne.createCell(0).setCellValue("总汇入金额");
        rowLastOne.createCell(4).setCellValue(amountSum.toPlainString());
        rowLastOne.setHeight((short) 400);
        for (int x = 0; x <= 5; x++) {
            // 创建缺失行
            if(x != 0 && x != 4) rowLastOne.createCell(x);
            //设置单元格样式
            if(x < 4) rowLastOne.getCell(x).setCellStyle(titleStyle);
            else rowLastOne.getCell(x).setCellStyle(titleStyleTwo);
        }

        // 本年总销售金额
        BigDecimal decimalB = mesWastesettleMapper.selectMesWasteBenSum(year);
        // 创建总销售金额
        sheet.addMergedRegion(new CellRangeAddress(i + 2, i + 2, 0, 3));
        sheet.addMergedRegion(new CellRangeAddress(i + 2, i + 2, 4, 5));
        // 创建合并行数据
        SXSSFRow rowLastTwo = sheet.createRow(i + 2);
        rowLastTwo.createCell(0).setCellValue("本年总销售金额");
        rowLastTwo.createCell(4).setCellValue(decimalB.toPlainString());
        rowLastTwo.setHeight((short) 400);
        for (int x = 0; x <= 5; x++) {
            // 创建缺失行
            if(x != 0 && x != 4) rowLastTwo.createCell(x);
            //设置单元格样式
            if(x < 4) rowLastTwo.getCell(x).setCellStyle(titleStyle);
            else rowLastTwo.getCell(x).setCellStyle(titleStyleTwo);
        }

        // 账户结余 = 上年结余金额 + （总汇入金额 - 本年总销售金额）
        BigDecimal add = decimal.add(amountSum.subtract(decimalB));
        sheet.addMergedRegion(new CellRangeAddress(i + 3, i + 3, 0, 3));
        sheet.addMergedRegion(new CellRangeAddress(i + 3, i + 3, 4, 5));
        // 创建合并行数据
        SXSSFRow rowLastThree = sheet.createRow(i + 3);
        rowLastThree.createCell(0).setCellValue("账户结余");
        rowLastThree.createCell(4).setCellValue(add.toPlainString());
        rowLastThree.setHeight((short) 400);
        for (int x = 0; x <= 5; x++) {
            // 创建缺失行
            if(x != 0 && x != 4) rowLastThree.createCell(x);
            //设置单元格样式
            if(x < 4) rowLastThree.getCell(x).setCellStyle(titleStyle);
            else rowLastThree.getCell(x).setCellStyle(titleStyleTwo);
        }

        // 创建第二页：废料处理明细
        SXSSFSheet sheet2 = swb.createSheet("废料处理统计查询");
        // 创建主标题行
        // 合并
        sheet2.addMergedRegion(new CellRangeAddress(0, 0, 0, 5));
        // 创建合并行数据
        SXSSFRow rowOne2 = sheet2.createRow(0);
        rowOne2.createCell(0).setCellValue(setting.getYears() + "年废料处理统计查询");
        rowOne2.setHeight((short) 800);
        for (int x = 0; x <= 5; x++) {
            // 创建缺失行
            if(x != 0) rowOne2.createCell(x);
            //设置单元格样式
            rowOne2.getCell(x).setCellStyle(titleStyleOne);
        }
        //【4】创建标题行
        SXSSFRow row2 = sheet2.createRow(1);
        row2.createCell(0).setCellValue("序号");
        row2.createCell(1).setCellValue("废品名称");
        row2.createCell(2).setCellValue("销售月份");
        row2.createCell(3).setCellValue("净重/吨");
        row2.createCell(4).setCellValue("价格/吨");
        row2.createCell(5).setCellValue("金额");
        for (int x = 0; x <= 5; x++) {
            //设置表格列宽度为5000个字节
            sheet2.setColumnWidth(x, 5000);
            //设置单元格样式
            row2.getCell(x).setCellStyle(titleStyle);
        }
        // 查询废料处理明细
        Map<String, Object> map = new HashMap<>();
        map.put("years", setting.getYears());
        List<WasteVo> list = mesWasteService.selectMesWasteDetailList(map);
        List<WasteVo> wasteVoList = new ArrayList<>();
        if(list.size() > 0){
            // 根据废品名称分组
            Map<String, List<WasteVo>> listMap = list.stream().collect(Collectors.groupingBy(WasteVo::getName));
            for (String s : listMap.keySet()) {
                // 依次获取废品信息
                List<WasteVo> wasteVos = listMap.get(s);
                BigDecimal weightNet = new BigDecimal(0); // 净重
                BigDecimal price = new BigDecimal(0); // 单价
                BigDecimal amount = new BigDecimal(0); // 金额
                for (WasteVo wasteVo : wasteVos) {
                    weightNet = weightNet.add(wasteVo.getWeightNet());
                    price = price.add(wasteVo.getPrice());
                    amount = amount.add(wasteVo.getAmount());
                }
                WasteVo wasteVo = new WasteVo();
                wasteVo.setName("小计");
                wasteVo.setWeightNet(weightNet);
                wasteVo.setPrice(price);
                wasteVo.setAmount(amount);
                wasteVoList.addAll(wasteVos);
                wasteVoList.add(wasteVo);
            }
        }
        int z = 2;
        // 判断是否有数据
        if(wasteVoList.size() > 0){
            CellStyle titleSum = swb.createCellStyle();
            titleSum.setAlignment(HorizontalAlignment.CENTER);// 水平居中
            titleSum.setVerticalAlignment(VerticalAlignment.CENTER);//垂直居中
            titleSum.setFillForegroundColor((short) 41);
            titleSum.setFillPattern(FillPatternType.SOLID_FOREGROUND);
            titleSum.setBorderBottom(BorderStyle.THIN); //下边框
            titleSum.setBorderLeft(BorderStyle.THIN);//左边框
            titleSum.setBorderTop(BorderStyle.THIN);//上边框
            titleSum.setBorderRight(BorderStyle.THIN);//右边框
            // 设置字体
            Font fontSum = swb.createFont();
            fontSum.setBold(true);
            titleSum.setFont(fontSum);
            SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy年MM月");
            for (WasteVo wasteVo : wasteVoList) {
                row2 = sheet2.createRow(z);
                String handleDate = "";
                if(wasteVo.getHandleDate() != null){
                    handleDate = dateFormat.format(wasteVo.getHandleDate());
                }
                row2.createCell(0).setCellValue(z - 1);
                row2.createCell(1).setCellValue(wasteVo.getName());
                row2.createCell(2).setCellValue(handleDate);
                row2.createCell(3).setCellValue(wasteVo.getWeightNet().toPlainString());
                row2.createCell(4).setCellValue(wasteVo.getPrice().toPlainString());
                row2.createCell(5).setCellValue(wasteVo.getAmount().toPlainString());
                // 设置样式
                for (int j = 0; j <= 5; j++) {
                    if("小计".equals(wasteVo.getName())){
                        row2.getCell(j).setCellStyle(titleSum);
                    }else {
                        row2.getCell(j).setCellStyle(cellStyle);
                    }
                }
                z++;
            }
        }


        OutputStream out = null;
        try {
            // 创建文件名
            SimpleDateFormat dateFormat = new SimpleDateFormat("yyyyMMdd-HHmmssSSS");
            String filename = dateFormat.format(new Date()) + "_结算信息.xlsx";
            String downloadPath = RuoYiConfig.getDownloadPath() + filename;
            File desc = new File(downloadPath);
            if (!desc.getParentFile().exists())
            {
                desc.getParentFile().mkdirs();
            }
            out = new FileOutputStream(downloadPath);
            swb.write(out);
            return AjaxResult.success(filename);
        } catch (Exception e) {
            throw new BaseException("导出Excel失败！" + e.getMessage());
        } finally {
            if (swb != null) {
                try {
                    swb.close();
                } catch (IOException e1) {
                    e1.printStackTrace();
                }
            }
            if (out != null) {
                try {
                    out.close();
                } catch (IOException e1) {
                    e1.printStackTrace();
                }
            }
        }
    }
}
